package com.simple.system.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.simple.common.exception.ServiceException;
import com.simple.framework.constant.HttpStatus;
import com.simple.system.domain.dto.AddSysRoleDto;
import com.simple.system.domain.dto.ListSysRoleDto;
import com.simple.system.domain.dto.UpdateRoleDto;
import com.simple.system.domain.entity.SysRole;
import com.simple.system.domain.vo.SysRoleVo;
import com.simple.system.mapper.SysMenuMapper;
import com.simple.system.mapper.SysRoleMapper;
import com.simple.system.mapper.SysUserMapper;
import com.simple.system.service.SysRoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;


/**
 * @Description 角色表(SysRole)表服务实现类
 * @Author xiaoke
 * @Date 2024/8/10 18:00
 * @Version 1.0
 */
@Service("sysRoleService")
public class SysRoleServiceImpl implements SysRoleService {

    private final SysRoleMapper sysRoleMapper;

    private final SysMenuMapper sysMenuMapper;

    private final SysUserMapper sysUserMapper;

    public SysRoleServiceImpl(SysRoleMapper sysRoleMapper, SysMenuMapper sysMenuMapper, SysUserMapper sysUserMapper) {
        this.sysRoleMapper = sysRoleMapper;
        this.sysMenuMapper = sysMenuMapper;
        this.sysUserMapper = sysUserMapper;
    }

    @Override
    public Page<SysRole> list(ListSysRoleDto dto) {
        Page<SysRole> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .like(dto.getName()!=null,SysRole::getName,dto.getName())
                .or()
                .like(dto.getName()!=null,SysRole::getCode,dto.getName())
                .orderByDesc(SysRole::getCreateTime);
        return sysRoleMapper.selectPage(page, queryWrapper);
    }

    @Override
    public SysRoleVo get(Long id) {
        return sysRoleMapper.findByIdDetails(id);
    }

    @Override
    public Boolean delete(Long id) {
        if(sysMenuMapper.checkRoleUse(id) > 0) {
            throw new ServiceException("该角色已分配给菜单，无法删除",HttpStatus.BAD_REQUEST);
        }
        if(sysUserMapper.checkRoleUse(id) > 0) {
            throw new ServiceException("该角色已分配给用户，无法删除",HttpStatus.BAD_REQUEST);
        }
        return sysRoleMapper.deleteById(id) == 1;
    }

    @Override
    @Transactional
    public Long insert(AddSysRoleDto dto) {
        checkRolePerms(dto.getPerms());
        if(sysRoleMapper.existRoleName(dto.getName()) != null) {
            throw new ServiceException("角色用户名已经存在",HttpStatus.BAD_REQUEST);
        }
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(dto,sysRole);
        sysRoleMapper.insert(sysRole);
        setRolePerms(dto.getPerms(),sysRole.getId());
        return sysRole.getId();
    }

    @Override
    @Transactional
    public void update(Long id, UpdateRoleDto dto) {
        SysRole sysRole = sysRoleMapper.selectById(id);
        if(sysRole == null) {
            throw new ServiceException("角色不存在",HttpStatus.BAD_REQUEST);
        }
        BeanUtils.copyProperties(dto,sysRole);
        SysRole tmpRole = sysRoleMapper.existRoleName(dto.getName());
        if(tmpRole != null && !tmpRole.getId().equals(id)) {
            throw new ServiceException("角色用户名不可用",HttpStatus.BAD_REQUEST);
        }
        checkRolePerms(dto.getPerms());
        sysRoleMapper.updateById(sysRole);
        setRolePerms(dto.getPerms(),id);
    }


    /**
     * 检查权限集合是否合格
     * @param perms 权限集合
     */
    private void checkRolePerms(Set<Long> perms){
        if (perms == null || perms.isEmpty()) return;
        Integer num = sysMenuMapper.existPerms(perms);
        if(num != perms.size()) {
            throw new ServiceException("权限集合存在不合格Id", HttpStatus.BAD_REQUEST);
        }
    }

    /**
     * 设置角色权限
     * @param ids 权限集合
     * @param id 角色Id
     */
    private void setRolePerms(Set<Long> ids,Long id){
        sysRoleMapper.deleteByIdPerms(id);
        if(ids != null && !ids.isEmpty()) {
            sysRoleMapper.insertAllPerms(ids,id);
        }
    }

}

